//
//  Extension+View.swift
//  TCMHealth
//
//  Created by 韩颖 on 2023/7/2.
//

import Foundation
import UIKit


extension UIView{
    /// 部分圆角
    ///
    /// - Parameters:
    ///   - corners: 需要实现为圆角的角，可传入多个
    ///   - radii: 圆角半径
    func corner(byRoundingCorners corners: UIRectCorner, radii: CGFloat) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radii, height: radii))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = self.bounds
        maskLayer.path = maskPath.cgPath
        self.layer.mask = maskLayer
    }
}


// MARK: Frame

extension UIView {
    var ls_x : CGFloat {
        get{
            return self.frame.origin.x
        }
        set{
            var curRect = self.frame;
            if (curRect.origin.x != newValue) {
                curRect.origin.x = newValue;
                self.frame = curRect;
            }
        }
    }
    var ls_y : CGFloat {
        get{
            return self.frame.origin.y
        }
        set{
            var curRect = self.frame;
            if (curRect.origin.y != newValue) {
                curRect.origin.y = newValue;
                self.frame = curRect;
            }
        }
    }
    var ls_width : CGFloat {
        get{
            return self.frame.size.width
        }
        set{
            var curRect = self.frame;
            if (curRect.size.width != newValue) {
                curRect.size.width = newValue;
                self.frame = curRect;
            }
        }
    }
    var ls_height: CGFloat {
        get{
            return self.frame.size.height
        }
        set{
            var curRect = self.frame;
            if (curRect.size.height != newValue) {
                curRect.size.height = newValue;
                self.frame = curRect;
            }
        }
    }
    var ls_origin : CGPoint{
        get{
            return self.frame.origin
        }
        set{
            var curRect = self.frame;
            if (!curRect.origin.equalTo(newValue)) {
                curRect.origin = newValue;
                self.frame = curRect;
            }
        }
    }
    var ls_size : CGSize{
        get{
            return self.frame.size
        }
        set{
            var curRect = self.frame;
            if (!curRect.size.equalTo(newValue)) {
                curRect.size = newValue;
                self.frame = curRect;
            }
        }
    }
    var ls_right : CGFloat { // (x + width).
        get{
            return self.frame.maxX
        }
    }
    var ls_bottom: CGFloat {  // (y + height).
        get{
            return self.frame.maxY
        }
    }
    var ls_centerX: CGFloat {   // (x + width/2).
        get{
            return self.frame.midX
        }
        set{
            var curCenter = self.center
            if (curCenter.x != newValue) {
                curCenter.x = newValue;
                self.center = curCenter;
            }
        }
    }
    var ls_centerY: CGFloat {   // (y + height/2).
        get{
            return self.frame.midY
        }
        set{
            var curCenter = self.center
            if (curCenter.y != newValue) {
                curCenter.y = newValue;
                self.center = curCenter;
            }
        }
    }
    
}


// MARK: Constraint

extension UIView {
    func ls_constraintForAttribute(attribute : NSLayoutConstraint.Attribute )->NSLayoutConstraint?{
        var constraintArray : [NSLayoutConstraint]
        
        if (attribute == .width || attribute == .height) {
            constraintArray = self.constraints
        } else {
            constraintArray = self.superview?.constraints ?? []
        }
            
       let fillteredArray =  constraintArray.filter{
           return $0.firstAttribute == attribute && ($0.firstItem as! NSObject == self || $0.secondItem as! NSObject == self)
        }
        
        return fillteredArray.first
        
    }
    
    var ls_constraintTop : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .top)
    }
    
    var ls_constraintBottom : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .bottom)
    }
    
    var ls_constraintLeading : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .left)
    }
    
    var ls_constraintTrailing : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .right)
    }
    
    var ls_constraintWidth : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .width)
    }
    
    var ls_constraintHeight : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .height)
    }
    
    var ls_constraintCenterX : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .centerX)
    }
    
    var ls_constraintCenterY : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .centerY)
    }
    ///基线指的的例如UILabel 的 文字的 Bottom 而不是控件的 bottom
    var ls_constraintBaseline : NSLayoutConstraint? {
        return self.ls_constraintForAttribute(attribute: .lastBaseline)
    }
    
    func ls_layoutPinnedToSuperview() {
        
        guard let superView =  self.superview else {return}
        self.translatesAutoresizingMaskIntoConstraints = false;
        self.rightAnchor.constraint(equalTo: superView.rightAnchor).isActive = true
        self.leftAnchor.constraint(equalTo: superView.leftAnchor).isActive = true
        self.bottomAnchor.constraint(equalTo: superView.bottomAnchor).isActive = true
        self.topAnchor.constraint(equalTo: superView.topAnchor).isActive = true
        
    }
    
}


// MARK: Layer
extension UIView {
    @IBInspectable var ls_cornerRadius :  CGFloat {
        get{
            return self.layer.cornerRadius
        }
        set{
            self.layer.cornerRadius = newValue
            if self.isKind(of: UIButton.self) || self.isKind(of: UIImageView.self) {
                self.layer.masksToBounds = (ls_cornerRadius > 0);
            }
        }
    }
    
    @IBInspectable var ls_masksToBounds : Bool {
        get{
            return self.layer.masksToBounds
        }
        set{
            if !self.isKind(of: UIButton.self) && !self.isKind(of: UIImageView.self) {
                self.layer.masksToBounds = newValue
            }
        }
    }
    
    @IBInspectable var ls_borderWidth : CGFloat {
        get{
            return self.layer.borderWidth
        }
        set{
            self.layer.borderWidth = newValue
        }
    }
    
    @IBInspectable var ls_borderColor : UIColor? {
        get{
            guard let borderColor = self.layer.borderColor else {return nil}
            return UIColor(cgColor: borderColor)
        }
        set{
            guard let borderColor = newValue?.cgColor else {return }
            self.layer.borderColor = borderColor
        }
    }
    
    @IBInspectable var ls_shadowColor : UIColor? {
        get{
            guard let shadowColor = self.layer.shadowColor else {return nil}
            return UIColor(cgColor: shadowColor)
        }
        set{
            guard let shadowColor = newValue?.cgColor else {return }
            self.layer.shadowColor = shadowColor
        }
    }
    
    @IBInspectable var ls_shadowOpacity : Float {
        get{
            return self.layer.shadowOpacity
        }
        set{
            self.layer.shadowOpacity = newValue
        }
    }
    
    @IBInspectable var ls_shadowOffset : CGSize {
        get{
            return self.layer.shadowOffset
        }
        set{
            self.layer.shadowOffset = newValue
        }
    }
    
    @IBInspectable var ls_shadowRadius : CGFloat {
        get{
            return self.layer.shadowRadius
        }
        set{
            self.layer.shadowRadius = newValue
        }
    }
    
    @IBInspectable var ls_shadowPath : Bool {
        get{
            guard self.layer.shadowRadius != 0 else {return false}
            return true
        }
        set{
            self.layer.shadowPath = UIBezierPath(rect: self.layer.bounds).cgPath
        }
    }
    
    
}

// MARK: GestureRecognizer
private var ls__TapGesKey = "ls__TapGesKey"
private var ls_handleTapGesKey = "ls_handleTapGesKey"

private var ls__LongPressGesKey = "ls__TapGesKey"
private var ls_handleLongPressGesKey = "ls_handleLongPressGes"

extension UIView {
    
    private var ls__TapGes : UITapGestureRecognizer? {
        get{return self.k_getAssociatedObjectWithKey(ckey:&ls__TapGesKey) as? UITapGestureRecognizer}
        set{ self.k_setAssociatedRetainObject(cValue: newValue, ckey: &ls__TapGesKey) }
    }
    
    private var ls__handleClouse_TapGes : ((_ cTapGes:UITapGestureRecognizer)->())? {
        get{return self.k_getAssociatedObjectWithKey(ckey:&ls_handleTapGesKey) as? (_ cTapGes: UITapGestureRecognizer) -> ()}
        set{ self.k_setAssociatedRetainObject(cValue: newValue, ckey: &ls_handleTapGesKey) }
    }
    
    private var ls__LongPressGes : UILongPressGestureRecognizer? {
        get{return self.k_getAssociatedObjectWithKey(ckey:&ls__LongPressGesKey) as? UILongPressGestureRecognizer}
        set{ self.k_setAssociatedRetainObject(cValue: newValue, ckey: &ls__LongPressGesKey) }
    }
    
    private var ls__handleClouse_LongPress : ((_ cLongPressGes:UILongPressGestureRecognizer)->())? {
        get{return self.k_getAssociatedObjectWithKey(ckey:&ls_handleLongPressGesKey) as? (_ cLongPressGes: UILongPressGestureRecognizer) -> ()}
        set{ self.k_setAssociatedRetainObject(cValue: newValue, ckey: &ls_handleLongPressGesKey) }
    }
    /**添加 tap 事件
     *新版的Swift闭包做参数默认是@noescaping，不再是@escaping。所以如果函数里异步执行该闭包，要添加@escaping。否则报错：Closure use of non-escaping parameter 'xxx' may allow it to escape.*
     **/
    func ls_addTapGes(cb:((_ cTapGes:UITapGestureRecognizer)->())?) {
        if !self.isUserInteractionEnabled { self.isUserInteractionEnabled = !self.isUserInteractionEnabled}

        if (self.ls__TapGes == nil) { //如果 view 本身不存在这个tap 事件,添加一个 curGesture 的属性
            let curGesture = UITapGestureRecognizer(target: self, action: #selector(ls_handleTapGes(tapGes:)))
            self.addGestureRecognizer(curGesture)
            self.ls__TapGes = curGesture
        }
        self.ls__handleClouse_TapGes = cb
    }

    ///触发点击事件
    @objc func ls_handleTapGes(tapGes : UITapGestureRecognizer) {
        self.ls__handleClouse_TapGes?(tapGes)
    }


    /**添加  长按 事件
     *新版的Swift闭包做参数默认是@noescaping，不再是@escaping。所以如果函数里异步执行该闭包，要添加@escaping。否则报错：Closure use of non-escaping parameter 'xxx' may allow it to escape.*
     **/
    func ls_addLongPressGes(cb: ((_ cLongPressGes:UILongPressGestureRecognizer)->())?) {
        if !self.isUserInteractionEnabled { self.isUserInteractionEnabled = !self.isUserInteractionEnabled}

        if (self.ls__LongPressGes == nil) { //如果 view 本身不存在这个tap 事件,添加一个 curGesture 的属性
            let curGesture = UILongPressGestureRecognizer(target: self, action: #selector(ls_handleLongPressGes(longPressGes:)))
            curGesture.numberOfTouchesRequired = 1
            self.addGestureRecognizer(curGesture)
            self.ls__LongPressGes = curGesture
        }
        self.ls__handleClouse_LongPress = cb
    }

    ///触发长按事件
    @objc func ls_handleLongPressGes(longPressGes : UILongPressGestureRecognizer) {
        self.ls__handleClouse_LongPress?(longPressGes)
    }
}




extension UIView {
    
    /** 获取最上层的视图 */
    func getTopView() -> UIView? {
        let windows = Array(UIApplication.shared.windows.reversed())
        for window in windows {
            let windowOnMainScreen = window.screen == UIScreen.main
            let isWindowVisible = !window.isHidden && window.alpha > 0
            let windowLevelSupport = window.windowLevel == UIWindow.Level.normal
            let isKeyWindow = window.isKeyWindow
            if windowOnMainScreen && isWindowVisible && windowLevelSupport && isKeyWindow {
                return window
            }
        }
        return k_currentWindow
    }
    
    func isValidView(view:UIView) -> Bool {
        if view.isEqual(k_currentWindow) {
            return true
        }else {
            return false
        }
    }
    
    /** 获取当前 view 所在的 controller  */
    func getViewOnController() -> UIViewController {
        var nextResponder:UIResponder?
        nextResponder = self.next
        repeat {
            if nextResponder as? UIViewController != nil {
                return (nextResponder as! UIViewController)
            }else {
                nextResponder = nextResponder?.next
            }
        }while nextResponder != nil
        
        return UIViewController()
    }
    
    var topVC: UIViewController? {
        var resultVC: UIViewController?
        resultVC = _topVC(UIApplication.shared.keyWindow?.rootViewController)
        while resultVC?.presentedViewController != nil {
            resultVC = _topVC(resultVC?.presentedViewController)
        }
        return resultVC
    }
    
    private  func _topVC(_ vc: UIViewController?) -> UIViewController? {
        if vc is UINavigationController {
            return _topVC((vc as? UINavigationController)?.topViewController)
        } else if vc is UITabBarController {
            return _topVC((vc as? UITabBarController)?.selectedViewController)
        } else {
            return vc
        }
    }
}

extension UIView {
    public func addGradientLayer(
        start: CGPoint = CGPoint(x: 0, y: 0), //渐变起点
        end: CGPoint = CGPoint(x: 0, y: 1), //渐变终点
        colors: [CGColor]
    ) {
        layoutIfNeeded()
        removeGradientLayer()
        let gradientLayer = CAGradientLayer()
        gradientLayer.startPoint = start
        gradientLayer.endPoint = end
        gradientLayer.frame = frame
        gradientLayer.colors = colors
        layer.insertSublayer(gradientLayer, at: 0)
    }
    
    
    // MARK: 添加渐变色图层
    public func gradientColor(_ startPoint: CGPoint, _ endPoint: CGPoint, _ colors: [Any]) {
        guard startPoint.x >= 0, startPoint.x <= 1, startPoint.y >= 0, startPoint.y <= 1, endPoint.x >= 0, endPoint.x <= 1, endPoint.y >= 0, endPoint.y <= 1 else {
            return
        }
        
        // 外界如果改变了self的大小，需要先刷新
        layoutIfNeeded()
        var gradientLayer: CAGradientLayer!
        removeGradientLayer()
        
        gradientLayer = CAGradientLayer()
        gradientLayer.frame = self.layer.bounds
        gradientLayer.startPoint = startPoint
        gradientLayer.endPoint = endPoint
        gradientLayer.colors = colors
        gradientLayer.cornerRadius = self.layer.cornerRadius
        gradientLayer.masksToBounds = true
        // 渐变图层插入到最底层，避免在uibutton上遮盖文字图片
        self.layer.insertSublayer(gradientLayer, at: 0)
        self.backgroundColor = UIColor.clear
        // self如果是UILabel，masksToBounds设为true会导致文字消失
        self.layer.masksToBounds = false
    }
    
    // MARK: 移除渐变图层
    // （当希望只使用backgroundColor的颜色时，需要先移除之前加过的渐变图层）
    public func removeGradientLayer() {
        guard let layers = self.layer.sublayers else { return }
        for layer in layers {
            if layer.isKind(of: CAGradientLayer.self) {
                layer.removeFromSuperlayer()
            }
        }
    }
    
    
    func makeCorner(radius:CGFloat) {
        self.layer.masksToBounds = true
        self.layer.cornerRadius = radius
    }
    
    func makeCorner(radius:CGFloat,color:UIColor?,borderWidth:CGFloat) {
        makeCorner(radius: radius)
        self.layer.borderColor = color?.cgColor
        self.layer.borderWidth = borderWidth
    }
    
    func makeCornerRadius(corner:UIRectCorner,size:CGSize) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corner, cornerRadii: size)
        let mask = CAShapeLayer()
        mask.frame = bounds
        mask.path = path.cgPath
        self.layer.mask = mask
    }
}

extension UIView {
    public var kl_x: CGFloat {
        get {
            return frame.origin.x
        }
        set {
            var f = frame
            f.origin.x = newValue
            frame = f
        }
    }
    
    public var kl_y: CGFloat {
        get {
            return frame.origin.y
        }
        set {
            var f = frame
            f.origin.y = newValue
            frame = f
        }
    }
    
    /// x
    var x: CGFloat {
        get {
            return frame.origin.x
        }
        set(newValue) {
            var tempFrame: CGRect = frame
            tempFrame.origin.x    = newValue.isNaN ? 0 : newValue
            frame                 = tempFrame
        }
    }
    
    /// y
    var y: CGFloat {
        get {
            return frame.origin.y
        }
        set(newValue) {
            var tempFrame: CGRect = frame
            tempFrame.origin.y    = newValue
            frame                 = tempFrame
        }
    }
    
    /// height
    var height: CGFloat {
        get {
            return frame.size.height
        }
        set(newValue) {
            var tempFrame: CGRect = frame
            tempFrame.size.height = newValue
            frame                 = tempFrame
        }
    }
    
    /// width
    var width: CGFloat {
        get {
            return frame.size.width
        }
        set(newValue) {
            if newValue.isNaN { return }
            var tempFrame: CGRect = frame
            if tempFrame.origin.x.isNaN { tempFrame.origin.x = 0 }
            if tempFrame.size.width.isNaN { tempFrame.size.width = 0 }
            tempFrame.size.width = newValue
            frame = tempFrame
        }
    }
    
    /// size
    var size: CGSize {
        get {
            return frame.size
        }
        set(newValue) {
            var tempFrame: CGRect = frame
            tempFrame.size = newValue
            frame = tempFrame
        }
    }
    
    /// centerX
    var centerX: CGFloat {
        get {
            return center.x
        }
        set(newValue) {
            var tempCenter: CGPoint = center
            tempCenter.x = newValue
            center = tempCenter
        }
    }
    
    /// centerY
    var centerY: CGFloat {
        get {
            return center.y
        }
        set(newValue) {
            var tempCenter: CGPoint = center
            tempCenter.y = newValue
            center = tempCenter;
        }
    }
    
    //middleX
    var middleX : CGFloat {
        get {
            return width / 2
        }
    }
    
    //middleY
    var middleY : CGFloat {
        get {
            return height / 2
        }
    }
    
    //middlePoint
    var middlePoint : CGPoint {
        get {
            return CGPoint(x: middleX, y: middleY)
        }
    }
    
    public var kl_bottom: CGFloat {
        get {
            return frame.maxY
        }
        set {
            kl_y = newValue - height
        }
    }
}
